/* 请求封装 */
import axios, { type AxiosRequestConfig } from 'axios'
import { dealWarning } from './status'
import { cutParamsInUrl } from './index'
import { getCommonHeadInfo } from '@/utils/chatHeaderInfo'
import { transformUrl } from './tools'

const handleError = dealWarning()

export const baseURL = import.meta.env.VITE_API_HOST

interface CustomConfigs {
  // 是否使用自定义的错误处理
  customError?: boolean
}

interface PendingTask {
  config: AxiosRequestConfig
  resolve: () => void
}
let refreshing = false
const queue: PendingTask[] = []

async function refreshToken() {
  return axios.request({
    url:
      `${transformUrl(baseURL)
      }${(import.meta as any).env.VITE_PASSPORT_PREFIX || ''}`
      + `/api/v1/user/token/refresh`,
    method: 'post',
    data: {
      refresh_token: localStorage.getItem('refresh_token'),
    },
    headers: {
      'Authorization': `Bearer ${localStorage.getItem('access_token')}`,
      'content-type': 'application/x-www-form-urlencoded',
    },
    withCredentials: true,
  })
}

function proxyService(params: any, customConfigs?: CustomConfigs) {
  const router = useRouter()
  const service = axios.create({
    baseURL: transformUrl(baseURL),
    timeout: 15000,
    withCredentials: true,
  })
  /** user api相关请求白名单 */
  const whiteList = [
    '/login',
    'login/mobile',
    '/sendVeriCode',
    '/register',
    '/quickLogin',
    '/quickRegister',
    '/forgetCode',
    '/forgetPassword',
    '/checkSameUser',
    '/token',
  ]

  const notAuthorization = (url: string = '') => {
    return whiteList.some(str => url.includes(str))
  }

  // request 拦截器
  service.interceptors.request.use(
    (config) => {
      // 配置请求头
      const currentRoute = router?.currentRoute?.value
      const title = config.headers['page-title'] || currentRoute?.meta?.reportTitle

      if (title) {
        // devpress接口不需要上报
        config.headers['page-title'] = encodeURIComponent(title)
      }

      config.headers['page-ref'] = encodeURIComponent(cutParamsInUrl(window.page_ref || document.referrer))
      config.headers['page-uri'] = encodeURIComponent(cutParamsInUrl(window.location.href || ''))

      Object.assign(config.headers, {
        ...getCommonHeadInfo(),
      })

      const access_token = window.localStorage.getItem('access_token')
      const { url } = config
      if (access_token && !notAuthorization(url)) {
        config.headers.Authorization = `Bearer ${access_token}`
      }
      return config
    },
    (error) => {
      return Promise.reject(error)
    },
  )

  // response 拦截器
  service.interceptors.response.use(
    (response) => {
      return response
    },
    async (error) => {
      const { response } = error
      const { config } = response
      if (refreshing) {
        return new Promise((resolve) => {
          queue.unshift({
            config,
            resolve,
          })
        })
      }
      if (
        response.status === 401
        && localStorage.getItem('access_token')
        && !config.url.includes('/token/refresh')
      ) {
        refreshing = true
        try {
          const res = await refreshToken()
          refreshing = false
          if (res.status === 200) {
            const { access_token, refresh_token } = res.data
            localStorage.setItem('access_token', access_token)
            localStorage.setItem('refresh_token', refresh_token)
            queue.forEach(({ config, resolve }) => {
              if (config.headers) {
                config.headers.Authorization = `Bearer ${access_token}`
              }
              resolve(axios(config))
            })
            queue.splice(0)
            config.headers.Authorization = `Bearer ${access_token}`
            return axios(config)
          }
          else {
            handleError({}, true)
            return Promise.reject(res.data)
          }
        }
        catch (e) {
          handleError({}, true)
        }
      }
      else if (response) {
        // 请求已发出，但是不在2xx的范围
        // showMessage(response);
        if (!customConfigs || !customConfigs.customError) {
          handleError(response)
        }
        return Promise.reject(response.data)
      }
      else {
        return Promise.reject(error)
      }
    },
  )

  return service(params)
}

export default proxyService
